package com.example.bookstore.service

import com.example.bookstore.dao.BaseDao
import com.example.bookstore.entity.BaseEntity
import com.example.bookstore.exception.IdentityNotExistException
import com.fasterxml.jackson.databind.ObjectMapper
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.data.domain.PageRequest
import org.springframework.data.domain.Sort

/**
 * Created by IntelliJ IDEA.
 * User: lvshe
 * Date: 2019/8/3
 * Time: 23:27
 */
@Suppress("SpringJavaAutowiredMembersInspection", "SpringJavaInjectionPointsAutowiringInspection")
open class BaseService<DAO : BaseDao<E>, E : BaseEntity> {

    @Autowired
    protected lateinit var dao: DAO
    @Autowired
    protected lateinit var objectMapper: ObjectMapper

    open fun getByIdOrNull(id: String): E? {
        return dao.findById(id).orElseGet { null }
    }

    open fun getById(id: String): E {
        return getByIdOrNull(id) ?: throw IdentityNotExistException(id)
    }

    open fun getByIds(ids: String): List<E> {
        return ids.split(",").map { getById(it) }
    }

    open fun getAll(): MutableList<E> {
        return dao.findAll()
    }

    open fun getAllPageable(page: Int, size: Int, sort: Sort = Sort.unsorted()): MutableList<E> {
        return dao.findAll(PageRequest.of(page, size, sort)).content
    }

    open fun save(entity: E): E {
        return dao.save(entity)
    }

    open fun saveAndFlush(entity: E): E {
        return dao.saveAndFlush(entity)
    }

    open fun saveAll(entities: MutableList<E>): MutableList<E> {
        return dao.saveAll(entities)
    }

    open fun deleteById(id: String) {
        return dao.delete(this.getById(id))
    }

    open fun deleteAll(entities: MutableList<E>) {
        return dao.deleteAll(entities)
    }

    open fun update(entity: E): E {
        getById(entity.id)
        return this.save(entity)
    }

    open fun updateWithJson(id: String, json: String): E {
        val entity = getById(id)
        val readValue = objectMapper.readerForUpdating(entity).readValue<E>(json)
        return save(readValue)
    }

}